package com.flynn.rock.crm.convert;

import com.flynn.rock.crm.entity.customer.CustomerEntity;
import com.flynn.rock.crm.entity.customer.CustomerFollowUpRecordEntity;
import com.flynn.rock.crm.entity.customer.CustomerOperateRecordEntity;
import com.flynn.rock.crm.entity.customer.CustomerOrderEntity;
import com.flynn.rock.crm.entity.customer.ReceiveCustomerEntity;
import com.flynn.rock.crm.model.ThirdPartyCustomerInfo;
import com.flynn.rock.crm.model.customer.request.NewInvitationRequest;
import com.flynn.rock.crm.model.customer.request.SaveCustomerRequest;
import com.flynn.rock.crm.model.customer.request.SaveFollowUpRecordRequest;
import com.flynn.rock.crm.model.customer.vo.CustomerVo;
import com.flynn.rock.crm.model.customer.vo.CustomerOrderVo;
import com.flynn.rock.crm.model.customer.vo.ListCustomerVo;
import com.flynn.rock.crm.model.customer.vo.ListFollowUpRecordVo;
import com.flynn.rock.crm.model.customer.vo.ListOperateRecordVo;
import com.flynn.rock.model.dto.CustomerOperateRecordDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.ReportingPolicy;
import org.mapstruct.factory.Mappers;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
public abstract class AbstractCustomerConvert {

    public static final AbstractCustomerConvert INSTANCE = Mappers.getMapper(AbstractCustomerConvert.class);

    public abstract CustomerEntity toCustomerEntity(ReceiveCustomerEntity entity);

    public abstract CustomerEntity toEntity(SaveCustomerRequest request);

    public abstract CustomerVo toDetailVo(CustomerEntity entity);

    public abstract ListCustomerVo toListCustomerVo(CustomerEntity entity);

    @Mapping(target = "applyTime", qualifiedByName = "toLocalDateTime")
    public abstract ReceiveCustomerEntity toReceiveCustomerEntity(ThirdPartyCustomerInfo customerInfo);

    @Mapping(target = "expectVisitTime", qualifiedByName = "toLocalDateTime")
    @Mapping(target = "createUserId", source = "userId")
    public abstract CustomerOrderEntity toCustomerOrderEntity(NewInvitationRequest request);

    public abstract CustomerFollowUpRecordEntity toFollowUpRecodeEntity(SaveFollowUpRecordRequest request);

    public abstract CustomerOperateRecordEntity toOperateRecordEntity(CustomerOperateRecordDto operateRecordDto);

    @Mapping(target = "expectVisitTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(target = "actualVisitTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(target = "expectLoanLimitTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(target = "actualLoanLimitTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    public abstract CustomerOrderVo toCustomerOrderVo(CustomerOrderEntity orderEntity);

    @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    public abstract ListFollowUpRecordVo toListFollowUpRecordVo(CustomerFollowUpRecordEntity entity);

    @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    public abstract ListOperateRecordVo toListOperateRecordVo(CustomerOperateRecordEntity entity);

    @Named("toLocalDateTime")
    static LocalDateTime toLocalDateTime(final Long dateMilliseconds) {
        if (dateMilliseconds == null) {
            return null;
        }
        return Instant.ofEpochMilli(dateMilliseconds).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }
}
